<?php
/**
 * +----------------------------------------------------------
 * @autor: luotao  装饰器模式
 * +----------------------------------------------------------
 * @Date : 2016/11/23 20:16
 * +----------------------------------------------------------
 */

namespace DesignPatterns\Structural\Decorator;

/**
 * RendererInterface接口
 */
interface RendererInterface
{
	/**
	 * render data
	 * @return mixed
	 */
	public function renderData();
}

/**
 * Webservice类
 */
class Webservice implements RendererInterface
{
	/**
	 * @var mixed
	 */
	protected $data;

	/**
	 * @param mixed $data
	 */
	public function __construct($data)
	{
		$this->data = $data;
	}

	/**
	 * @return string
	 */
	public function renderData()
	{
		return $this->data;
	}
}

/**
 * 装饰器必须实现 RendererInterface 接口, 这是装饰器模式的主要特点，
 * 否则的话就不是装饰器而只是个包裹类
 */

/**
 * Decorator类
 */
abstract class Decorator implements RendererInterface {
	/**
	 * @var RendererInterface
	 */
	protected $wrapped;

	/**
	 * 必须类型声明装饰组件以便在子类中可以调用renderData()方法
	 * @param RendererInterface $wrappable
	 */
	public function __construct (RendererInterface $wrappable) {
		$this->wrapped = $wrappable;
	}
}

/**
 * RenderInXml类
 */
class RenderInXml extends Decorator
{
	/**
	 * render data as XML
	 *
	 * @return mixed|string
	 */
	public function renderData()
	{
		$output = $this->wrapped->renderData();

		// do some fancy conversion to xml from array ...

		$doc = new \DOMDocument();

		foreach ($output as $key => $val) {
			$doc->appendChild($doc->createElement($key, $val));
		}

		return $doc->saveXML();
	}
}

/**
 * RenderInJson类
 */
class RenderInJson extends Decorator
{
	/**
	 * render data as JSON
	 *
	 * @return mixed|string
	 */
	public function renderData()
	{
		//调用传入的Webservice类的renderData方法，获取被装饰的内容
		$output = $this->wrapped->renderData();

		return json_encode($output);
	}
}


$WebService = new Webservice(['haha'=>1,'heihei'=>2]);
$Render = new RenderInJson($WebService);
var_dump($Render->renderData());
$Render = new RenderInXml($WebService);
var_dump($Render->renderData());
